package com.woniuxy.yygh.cmn.config;


import com.woniuxy.yygh.annotations.MyDictCode;
import com.woniuxy.yygh.model.cmn.Dict;
import org.springframework.beans.BeanUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * <P> @Author: ideaAdmin
 * <P> TODO: Class
 * <P> TODO: 字典工具类
 * <P> Date: 2022/4/21:17:55
 * <P> Description:
 */

public class DictUtils {

    private static final
    AtomicReference<PickInterface> ATOMIC_REFERENCE
            = new AtomicReference<>();


    /**
     * <P>Author ideaAdmin
     * <P>TODO: 遍历list封装数据
     * <P>Date 23:10 2022/4/21
     * <P>* @param targetList
     * <P>* @return java.util.List<?>
     **/
    public static List<?> setListDict(List<?> targetList) {

        if (targetList.size() <= 0) {
            throw new NullPointerException();
        }

        if (ATOMIC_REFERENCE.get() == null) {
            ATOMIC_REFERENCE.set(new PackDict());
        }


        LinkedList<Object> returnList = new LinkedList<>();
        targetList.forEach(node -> {
            returnList.add(ATOMIC_REFERENCE.get().setDict(node));
        });

        return returnList;
    }

    /**
     * <P>Author ideaAdmin
     * <P>TODO: 封装单个实体的字典
     * <P>Date 9:10 2022/4/22
     * <P>* @param target
     * <P>* @return org.apache.poi.ss.formula.functions.T
     **/
    public static<T> T setDict(T target) {

        if (ATOMIC_REFERENCE.get() == null) {
            ATOMIC_REFERENCE.set(new PackDict());
        }
        return ATOMIC_REFERENCE.get().setDict(target);
    }

    public static PickInterface getPackDict() {
        return ATOMIC_REFERENCE.get();
    }

    public static void setPackDict(PickInterface packDict) {
        ATOMIC_REFERENCE.set(packDict);
    }

    static class PackDict implements PickInterface {
        private boolean isFind;

        /**
         * <P>Author ideaAdmin
         * <P>TODO: 传入一个对象 对其进行封装
         * <P>Date 22:53 2022/4/21
         * <P>* @param target
         * <P>* @return T
         **/
        @Override
        public <T> T setDict(T target) {

            Class<?> tClass = target.getClass();

            Object targetClone = null;
            try {
                targetClone = tClass.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
                return target;
            }

            BeanUtils.copyProperties(target, targetClone);

            Field[] declaredFields = tClass.getDeclaredFields();

            try {
                getMyField(declaredFields, target, (T) targetClone);
                return (T) targetClone;
            } catch (Exception e) {
                e.printStackTrace();
                return target;
            }

        }

        /**
         * <P>Author ideaAdmin
         * <P>TODO: 设置当前对象的所有属性
         * <P>Date 22:15 2022/4/21
         * <P>* @param declaredFields
         *
         * @param target
         * @param targetClone <P>* @return java.lang.reflect.Field
         **/
        protected static <T> Field getMyField(Field[] declaredFields, T target, T targetClone) throws Exception {
            for (Field declaredField : declaredFields) {

                //TODO 如果拥有注解
                //获得我想要的注解
                if (isHaveAnnotations(declaredField) != null) {
                    Map<String, Annotation> annotations = getAnnotations(declaredField);
                    //TODO 获得数组对象 然后获得缓存的数据 遍历缓存 然后设置值

                    //TODO 获得dict的当前子类 获得它的注解值
                    MyDictCode myDictCode = (MyDictCode) annotations.get("dict");
                    setValue(myDictCode, declaredField, target, targetClone);
                }

            }
            return null;
        }

        /**
         * <P>Author ideaAdmin
         * <P>TODO: 设置属性值
         * <P>Date 8:33 2022/4/22
         * <P>* @param myDictAnno
         *
         * @param field
         * @param target
         * @param targetClone <P>* @return void
         **/
        protected static <T> void setValue(Annotation myDictAnno, Field field, T target, T targetClone) throws NoSuchFieldException, IllegalAccessException {
            List<Dict> collect = DictRedisCache.dictCache.entrySet()
                    .stream()
                    .map(Map.Entry::getValue)
                    .collect(Collectors.toList());

            AtomicReference<MyDictCode> myDictCodeAtomicReference = new AtomicReference<>();
            if (myDictAnno instanceof MyDictCode) {
                myDictCodeAtomicReference.set((MyDictCode) myDictAnno);
            }

            if (myDictCodeAtomicReference.get() == null) {
                return;
            }
            //TODO  如果当前有直接父级菜单
            if (!myDictCodeAtomicReference.get().isSon()) {
                ifNoSon(field, targetClone, collect, myDictCodeAtomicReference);
                return;
            }


            // TODO 否则获取属性值去查询
            String value = myDictCodeAtomicReference.get().value();
            // 获得父类菜单的属性
            Field declaredField = target.getClass().getDeclaredField(value);
            declaredField.setAccessible(true);

            // 获得父类菜单的注解
            Map<String, Annotation> annotations = getAnnotations(declaredField);
            myDictCodeAtomicReference.set((MyDictCode) annotations.get("dict"));
            Dict fartherDict = ifNoSon(declaredField, target, collect, myDictCodeAtomicReference);

            if (fartherDict == null) {
                throw new RuntimeException("当前附加菜单为空");
            }

            // 获得父级菜单的id 通过dictcode和value查询
            // 查找当前父级菜单下面的所有的list
            List<Dict> collect1 = collect.stream().filter(dict -> {
                return dict.getParentId().compareTo(fartherDict.getId()) == 0;
            }).collect(Collectors.toList());

            setTargetClone(field, target, targetClone, collect1);


        }


        /**
         * <P>Author ideaAdmin
         * <P>TODO: 如果当前就是二级菜单 调用这个方法
         * <P>Date 22:12 2022/4/2 1
         * <P>* @param field
         *
         * @param targetClone
         * @param collect
         * @param myDictCodeAtomicReference <P>* @return com.woniuxy.ann.Dict
         **/
        protected static <T> Dict ifNoSon(Field field, T targetClone, List<Dict> collect,
                                          AtomicReference<MyDictCode> myDictCodeAtomicReference) {
            // 获得对应的字典列表的父级菜单字典
            Optional<Dict> first = collect.stream().filter(dict -> {

                return dict.getDictCode().equals(myDictCodeAtomicReference.get().value());

            }).findFirst();


            AtomicReference<Dict> myDict = new AtomicReference<>();

            first.ifPresent(myDict::set);

            List<Dict> collect1 = null;

            if (myDict.get() == null) {
                return null;
            }
            //TODO 获得对应的字典List 集合
            collect1 = collect.stream().filter(dict -> {
                        return dict.getParentId().compareTo(myDict.get().getId()) == 0;
                    })
                    .collect(Collectors.toList());


            return setTargetClone(field, targetClone, targetClone, collect1);
        }


        /**
         * <P>Author ideaAdmin
         * <P>TODO: 根据target的设置其对应的属性值
         * <P>Date 22:10 2022/4/21
         * <P>* @param field
         *
         * @param target
         * @param targetClone
         * @param collect1    <P>* @return com.woniuxy.ann.Dict
         **/
        protected static <T> Dict setTargetClone(Field field, T target, T targetClone, List<Dict> collect1) {
            field.setAccessible(true);


            // 获得对应的字典
            Optional<Dict> optionalDict = collect1.stream()
                    .filter(dict -> {
                        try {
                            return dict.getValue().compareTo(String.valueOf(Long.valueOf(field.get(target).toString()))) == 0;
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                        return false;
                    }).
                    findFirst();

            optionalDict.ifPresent(dict -> {
                try {
                    field.set(targetClone, dict.getName());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            });

            // 写入到对应的字段
            AtomicReference<Dict> source = new AtomicReference<>();
            optionalDict.ifPresent(dict -> {
                try {
                    source.set(dict);
                    field.set(targetClone, dict.getName());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            });
            return source.get() == null ? null : source.get();
        }

        /**
         * <P>Author ideaAdmin
         * <P>TODO: 是否拥有自定义注解
         * <P>Date 22:14 2022/4/21
         * <P>* @param declaredField
         * <P>* @return java.lang.reflect.Field
         **/
        protected static Field isHaveAnnotations(Field declaredField) {
            Annotation[] annotations = declaredField.getAnnotations();
            if (annotations.length > 0 &&
                    isHaveMyDict(declaredField) &&
                    isHaveMyExcel(declaredField)
            ) {
                return declaredField;
            }
            return null;
        }

        /**
         * TODO: 是否拥有 MyDict 注解 和 MyExcel 注解
         **/
        protected static boolean isHaveMyDict(Field declaredField) {
            Annotation[] annotations = declaredField.getAnnotations();
            for (Annotation annotation : annotations) {
                if (annotation instanceof MyDictCode) {
                    return true;
                }
            }
            return false;
        }

        /**
         * <P>Author ideaAdmin
         * <P>TODO: 是否有MyExcel注解 删除 默认返回true 懒得改了
         * <P>Date 22:14 2022/4/21
         * <P>* @param declaredField
         * <P>* @return boolean
         **/
        protected static boolean isHaveMyExcel(Field declaredField) {
            Annotation[] annotations = declaredField.getAnnotations();
            for (Annotation annotation : annotations) {
                if (annotation instanceof MyDictCode) {
                    return true;
                }
            }
            return true;
        }

        /**
         * <P>Author ideaAdmin
         * <P>TODO: 是否有myDict注解
         * <P>Date 22:15 2022/4/21
         * <P>* @param declaredField
         * <P>* @return java.util.Map<java.lang.String,java.lang.annotation.Annotation>
         **/
        protected static Map<String, Annotation> getAnnotations(Field declaredField) {
            Annotation[] annotations = declaredField.getAnnotations();
            Map<String, Annotation> myAnno = new HashMap();

            for (Annotation annotation : annotations) {
                if (annotation instanceof MyDictCode) {
                    myAnno.put("dict", annotation);
                }

            }
            return myAnno;

        }
    }

}
